package top.jolyoulu.webcommon.encrypt;

import lombok.extern.slf4j.Slf4j;
import top.jolyoulu.corecommon.utils.encryption.AESUtils;
import top.jolyoulu.webcommon.filter.MultiReadHttpServletRequestWrapper;
import top.jolyoulu.webcommon.filter.MultiReadHttpServletResponseWrapper;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Map;
import java.util.Objects;

/**
 * @Author: JolyouLu
 * @Date: 2023/1/21 16:17
 * @Description 使用AES的加密解密过滤器
 */
@Slf4j
public class AesEncryptFilter implements Filter {

    private final String key;

    public AesEncryptFilter(String key) {
        this.key = key;
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws ServletException, IOException {
        //判断是否是包装过的servlet
        if (servletRequest instanceof MultiReadHttpServletRequestWrapper
                && servletResponse instanceof MultiReadHttpServletResponseWrapper
                && isEncrypt(servletRequest)) {
            MultiReadHttpServletRequestWrapper requestWrapper = (MultiReadHttpServletRequestWrapper) servletRequest;
            MultiReadHttpServletResponseWrapper responseWrapper = (MultiReadHttpServletResponseWrapper) servletResponse;
            try {
                decryptParameter(requestWrapper);
                decryptBody(requestWrapper);
                filterChain.doFilter(servletRequest, servletResponse);
                encryptBody(responseWrapper);
            } catch (Exception e) {
                servletResponse.getOutputStream().write("{\"code\":500,\"message\":\"加密/解密失败\"}".getBytes());
            } finally {
                //对body加密
                encryptBody(responseWrapper);
            }
        } else {
            filterChain.doFilter(servletRequest, servletResponse);
        }
    }

    /**
     * 对url中?后面的数据进行解密
     */
    private void decryptParameter(MultiReadHttpServletRequestWrapper requestWrapper) {
        Map<String, String[]> parameterMap = requestWrapper.getParameterMap();
        if (Objects.nonNull(parameterMap)) {
            String ciphertext = parameterMap.keySet().iterator().next();
            String decrypt = AESUtils.decrypt(ciphertext, key);
            for (String parameter : decrypt.split("&")) {
                String[] kv = parameter.split("=");
                requestWrapper.addParameter(kv[0], kv[1]);
            }
            requestWrapper.delParameter(ciphertext);
        }
    }

    /**
     * 对body中的数据进行解密
     */
    private void decryptBody(MultiReadHttpServletRequestWrapper requestWrapper) {
        String decrypt = AESUtils.decrypt(requestWrapper.getBytes(), key);
        requestWrapper.setBytes(decrypt.getBytes());
    }

    /**
     * 对body中的数据进行加密
     */
    private void encryptBody(MultiReadHttpServletResponseWrapper responseWrapper) throws IOException {
        String encrypt = AESUtils.encrypt(responseWrapper.toByteArray(), key);
        ByteArrayOutputStream byteArrayOutputStream = responseWrapper.getByteArrayOutputStream();
        //重置流
        byteArrayOutputStream.reset();
        byteArrayOutputStream.write(encrypt.getBytes());
    }

    /**
     * 是否需要加密
     *
     * @return false跳过加密, true开启加密
     */
    private boolean isEncrypt(ServletRequest servletRequest) {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        return true;
    }


}
